package com.qianda.qdminiapp.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 认证过滤器，用于根据用户传递的令牌生成认证信息
 * @ClassName AuthenticationFilter
 * @Author cw
 * @Date 2019/7/1 10:23
 **/
public class AuthenticationFilter extends OncePerRequestFilter {


    private static final Logger LOG = LoggerFactory.getLogger(AuthenticationFilter.class);

    public static final String TOKEN_HEADER = "Token";

    private TokenManager tokenManager;

    /**
     * 构造认证过滤器
     *
     * @param manager 令牌管理器
     */
    public AuthenticationFilter(TokenManager manager) {
        if (manager == null) {
            throw new IllegalArgumentException("TokenManager is required");
        }
        this.tokenManager = manager;
    }

    @Override
    protected void doFilterInternal(
            HttpServletRequest req,
            HttpServletResponse resp,
            FilterChain chain) throws ServletException, IOException {

        String tokenId = req.getHeader(TOKEN_HEADER);

        // 不存在令牌请求头
        if (StringUtils.isEmpty(tokenId)) {
            chain.doFilter(req, resp);
            return;
        }

        // 获取认证信息
        Authentication authResult = tokenManager.getAuthResult(tokenId);
        if (authResult == null) {
            LOG.info("No authentication of token {}", tokenId);
            // 没有获取到认证信息
           throw new InvalidTokenException();
           // throw new SimpleException(ExceptionCode.EX_HTTP_ACCESS_DENIED);
           // throw new ServiceException("访问被拒绝");
        }

        SecurityContextHolder.getContext().setAuthentication(authResult);

        chain.doFilter(req, resp);
    }


}
